package cn.com.jinhao.provider.user.controller;


import cn.com.jinhao.hotline.commons.base.constant.SystemConstant;
import cn.com.jinhao.hotline.commons.controller.BaseController;
import cn.com.jinhao.hotline.commons.exception.ParamErrorException;
import cn.com.jinhao.hotline.commons.util.RestResponse;
import cn.com.jinhao.hotline.commons.util.Utils;
import cn.com.jinhao.hotline.commons.vo.user.LoginRequestVo;
import cn.com.jinhao.hotline.commons.vo.TestUser;
import cn.com.jinhao.provider.user.entity.Dept;
import cn.com.jinhao.provider.user.entity.Role;
import cn.com.jinhao.provider.user.entity.User;
import cn.com.jinhao.provider.user.service.DeptService;
import cn.com.jinhao.provider.user.service.RedisService;
import cn.com.jinhao.provider.user.service.RoleService;
import cn.com.jinhao.provider.user.service.UserService;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.*;

/**
 * 用户服务控制器
 *
 * @author ShaneMew
 */
@RestController
@RequestMapping("/users")
@Api(tags = "用户服务")
public class UserController extends BaseController {
    @Resource
    private UserService userService;
    @Resource
    private DeptService deptService;
    @Resource
    private RoleService roleService;
    @Resource
    private RedisService redisService;


    @ApiOperation(value = "查询用户", notes = "根据用户编码查询用户信息")
    @ApiImplicitParam(name = "code", value = "用户编码", required = true, dataType = "String")
    @GetMapping
    public RestResponse<User> queryUser(@RequestParam String code) throws Exception {
        User user = userService.queryByCode(code);
        if (Optional.ofNullable(user).isPresent()) {
            String deptCode = deptService.queryDeptCodeByUserCode(code);
            Dept dept = deptService.queryByDeptCode(deptCode);
            List<Role> roles = roleService.queryRoles(code);
            user.setRoles(roles);
            user.setDept(dept);
            return new RestResponse<>(user);
        } else {
            return new RestResponse<>(SystemConstant.ResponseCode.DATA_NOT_EXIST, null);
        }
    }

    @ApiOperation(value = "用户名称查询", notes = "根据用户编码查询用户名称")
    @GetMapping(value = "/queryNameByCode")
    public String getNameByCode(@RequestParam("code") String code) throws Exception{
            return userService.getNameByCode(code);
    }

    @ApiOperation(value = "查询用户信息")
    @GetMapping(value = "/queryUserByCode")
    public RestResponse<User> queryUserByCode(@RequestParam String code) throws Exception {
        User user = userService.queryByCode(code);
        return new RestResponse<>(user);
    }

    @ApiOperation(value = "验证用户是否属于部门", notes = "根据用户编码查询当前用户的部门编码是否一致")
    @GetMapping(value = "/checkUserByCodeAndDept")
    public boolean checkUserByCodeAndDept(@RequestParam String code, @RequestParam String deptCode) throws Exception {
        return deptCode.equals(deptService.queryDeptCodeByUserCode(code));
    }

    @ApiOperation(value = "创建用户", notes = "根据User对象创建用户")
    @PostMapping
    public RestResponse<User> addUser(@ApiParam(name = "用户信息", value = "用户信息", required = true) @Valid @RequestBody User user, BindingResult result) throws Exception{
        validate(result);
        return this.executeMethod(user, SystemConstant.DataOperType.DATA_OPER_TYPE_ADD.getValue());
    }


    @ApiOperation(value = "更新用户", notes = "根据用户编码更新用户信息")
    @PutMapping
    public RestResponse<User> updateUser(@ApiParam(name = "用户信息", value = "用户信息", required = true) @RequestBody User user) throws Exception{
        if (StringUtils.isBlank(user.getCode())) {
            throw new ParamErrorException("用户编码不能为空");
        }
        return this.executeMethod(user, SystemConstant.DataOperType.DATA_OPER_TYPE_UPDATE.getValue());
    }

    @ApiOperation(value = "删除用户", notes = "根据用户编码删除用户信息")
    @DeleteMapping
    public RestResponse<User> deleteUser(@ApiParam(name = "code", value = "用户编码", required = true)@RequestParam String code) throws Exception {
        return this.executeMethod(code, SystemConstant.DataOperType.DATA_OPER_TYPE_DEL.getValue());
    }

    @ApiOperation(value = "用户登录", notes = "测试用途")
    @PostMapping(value = "/testLogin")
    public RestResponse<Object> testLogin(@ApiParam(name = "loginVo", value = "用户登录信息", required = true) @Valid @RequestBody LoginRequestVo loginRequestVo, BindingResult result) {
        validate(result);
        String loginStr = "[{\"code\":\"ceshi1\",\"password\":\"123456\",\"edition\": ['HuNan','YiYang', 'AXian1', 'BXiang1', 'CCun1']}," +
            "{\"code\":\"ceshi2\",\"password\":\"123456\",\"edition\": ['HuNan','YiYang', 'AXian2', 'BXiang2', 'CCun2']}" +
            "{\"code\":\"ceshi3\",\"password\":\"123456\",\"edition\": ['HuNan', 'YiYang','AXian3','BXiang3','CCun3']}]";
        List<TestUser> jsArr = JSONObject.parseArray(loginStr, TestUser.class);
        TestUser user = jsArr.stream().filter(s -> s.getCode().equals(loginRequestVo.getUsername())).findFirst().orElse(null);
        if (Optional.ofNullable(user).isEmpty()) {
            return new RestResponse<>(SystemConstant.ResponseCode.DATA_NOT_EXIST, null);
        }
        return new RestResponse<>(user);
    }

    @ApiOperation(value = "用户登录", notes = "用户登录")
    @ApiResponses({
        @ApiResponse(code = 200, message = "OK", response = RestResponse.class)
    })
    @PostMapping(value = "/login")
    public RestResponse<Object> login(@ApiParam(name = "loginVo", value = "用户登录信息", required = true) @Valid @RequestBody LoginRequestVo loginRequestVo, BindingResult result) throws Exception {
        validate(result);
        String currentToken = null;
        Set<String> keys = redisService.keys();
        for (String key: keys) {
            String value = redisService.get(key);
            JSONObject jsonObject = (JSONObject)JSONObject.parse(value);
            if (loginRequestVo.getUsername().equals(jsonObject.getString("name"))) {
                currentToken = key;
            }
        }
//        String currentToken = redisService.get(loginRequestVo.getUsername());
        if (StringUtils.isNoneBlank(currentToken)) {
//            redisService.setString(currentToken, loginRequestVo.getUsername());
//            redisService.setString(loginRequestVo.getUsername(), currentToken);
            String userInfo = redisService.get(currentToken);
//            String tokenJson = "{\"token\":\"" + currentToken + "\"}";
            return new RestResponse<>(JSON.parseObject(userInfo));
        } else {
            User user = userService.login(loginRequestVo);
            if (Optional.ofNullable(user).isPresent()) {
                if (loginRequestVo.getPassword().equals(user.getPass())) {

                    String token = Utils.generateToken(loginRequestVo.getUsername());
                    String tokenJson = "{\"token\":\"" + token + "\"}";


//                    redisService.setString(user.getCode(), token);
                    String code = loginRequestVo.getUsername();
                    User userInfo = userService.queryByCode(code);
                    String deptCode = deptService.queryDeptCodeByUserCode(code);
                    Dept dept = deptService.queryByDeptCode(deptCode);
                    List<Role> roles = roleService.queryRoles(code);
                    userInfo.setRoles(roles);
                    userInfo.setDept(dept);
                    Map<String, Object> resResult = new HashMap<>();
                    resResult.put("user", userInfo);
                    resResult.put("token",JSON.parseObject(tokenJson));
                    resResult.put("edition",JSON.parse("{\"edition\": ['HuNan', 'YiYang','AXian3','BXiang3','CCun3']}"));
                    redisService.setString(token, JSONUtil.parseObj(resResult).toStringPretty());
                   return new RestResponse<>(resResult);

                } else {
                    return new RestResponse<>(SystemConstant.ResponseCode.USER_PASSWORD_INCORRECT, null);
                }
            } else {
                return new RestResponse<>(SystemConstant.ResponseCode.DATA_NOT_EXIST, null);
            }
        }
    }

    private RestResponse<User> executeMethod(Object obj, int methodType) throws Exception{
            switch (Objects.requireNonNull(SystemConstant.DataOperType.getByValue(methodType))) {
                case DATA_OPER_TYPE_UPDATE:
                    userService.update((User) obj);
                    break;
                case DATA_OPER_TYPE_DEL:
                    userService.delete(obj.toString());
                    break;
                default:
                    userService.add((User) obj);
                    break;
            }
            return new RestResponse<>(null);
    }
}
